﻿using log4net;
using System;
using System.Reflection;
using WpfApp1.Acme.ApplicationAttribute;
using WpfApp1.Acme.ApplicationClass;
using WpfApp1.Acme.Template;

namespace WpfApp1.Acme.TemplateImpl {
    /// <summary>
    /// 程序上下文
    /// </summary>
    internal class ApplicationContext : BeanFactory {
        /** 日志对象 */ 
        private static readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        /** 数据源操作对象 */
        private static DataSourceOperation dataSourceOperation;
        /// <summary>
        /// 获取当前程序集
        /// </summary>
        /// <returns></returns>
        public static Assembly getExecutingAssembly() {
           return Assembly.GetExecutingAssembly();
        }

        /// <summary>
        /// 运行框架程序
        /// </summary>
        /// <param name="configurationClass"></param>
        public static void run(in Type configurationClass) {
            Assembly assembly = ApplicationBeanDefinitionScanner.get().loadPackage();

            Attribute componentScan = assembly.GetType(configurationClass.FullName)?.GetCustomAttribute(typeof(ComponentScan));
            if (componentScan is not null) {
                // 扫描程序集
                ExecutionAttribute.getAttributeTwoStrategy()[componentScan.GetType()](assembly, componentScan);

                // 扫描数据源
                Attribute dataSource = assembly.GetType(configurationClass.FullName)?.GetCustomAttribute(typeof(DataSource));
                if (dataSource is not null) { 
                   dataSourceOperation = ExecutionAttribute.getAttributeTwoStrategy()[dataSource.GetType()](assembly, dataSource); 
                } 
                else { logger.Error("找不到DataSoure特性，未配置数据源"); }
                
                // 实例化单例bean
                instanceSingletionBean();
            } else {
                logger.Error("找不到 " + configurationClass.FullName + " 配置类配置的包路径");
            }
        }

        /// <summary>
        /// 获取bean
        /// </summary>
        /// <param name="beanName"></param>
        /// <returns></returns>
        public static object getBean(in string beanName) {
            bool isNoContainsBeanName = !getBeanDefinitionMap().ContainsKey(beanName);
            object bean = null;
            try {
                if (isNoContainsBeanName) { logger.Error("BeanDifinitionMap 注册池里没有 " +beanName); }
                BeanDefinition beanDefinition = getBeanDefinitionMap()[beanName];
                
                if (beanDefinition.Scope.Equals(ScopeType.prototype)) {
                    bean = createBean(beanDefinition);
                } else {
                    
                    bool beanNameIsNoContainsBeanMap = !getBeanMap().ContainsKey(beanName);
                    if (getBeanMap().ContainsKey(beanName)) {
                        bean = getBeanMap()[beanName];
                    }
                    
                    if (bean == null || beanNameIsNoContainsBeanMap) {
                        bean = createBean(beanDefinition);
                        getBeanMap().TryAdd(beanName, bean);
                    }
                }
            } catch (Exception ex) {
                logger.Error(ex.Message);
            }
            return bean;
        }
        /// <summary>
        /// 数据源操作类构造器，用于对数据库的操作，在App.config
        /// 文件中配置了数据源连接字符串会自动调用connect方法来连
        /// 接数据源。获取数据源操作类的方法，来操作数据库
        /// </summary>
        /// <returns></returns>
        public static DataSourceOperation getDataSourceOperation() { return dataSourceOperation; }
    }
}
